二叉树是一种树形数据结构,它的每个节点最多有两个孩子,被叫作左孩子和右孩子。二叉树可以用于二叉查找,哈夫曼树等算法。
常见特殊二叉树:
对于一棵二叉树,如果每一个非叶子节点都存在左右子树,并且二叉树中所有的叶子节点都在同一层中,这样的二叉树称为满二叉树。
完全二叉树
对于一棵具有n
个节点的二叉树按照层次编号,同时,左右子树按照先左后右编号,如果编号为i
的节点与同样深度的满二叉树中编号为i
的节点在二叉树中的位置完全相同,则这棵二叉树称为完全二叉树。
二叉树实现:
用链式结构表示树,每个树节点由value,指向左孩子的指针和指向右孩子的指针组成。
1 | package structures; |
深度优先遍历
二叉树遍历分为深度遍历和广度遍历。
深度遍历又分为(相对根的位置来划分):
- 先序遍历:根–左孩子–右孩子
- 中序遍历:左孩子–根–右孩子
- 后序遍历: 左孩子–右孩子–根
递归实现
深度遍历三种顺序实现:
1 | /** |
测试:
1 | public static void main(String arg[]){ |
先序遍历:
1 2 4 5 7 8 3 6
中序遍历:
4 2 7 5 8 1 3 6
后序遍历:
4 7 8 5 2 6 3 1
非递归实现(栈)
非递归实现相比递归复杂很多,深度遍历我们需要用栈保存父节点
先序遍历
先访问根节点再访问左孩子右孩子,我们从根开始,先输出父节点,再读取左孩子并将父节点压入栈中,重复至左孩子为null,将父节点出栈,开始遍历右子树。我们保留父节点再栈内是为了访问完左子树后可以得到右子树。
java实现:
1 | /** |
中序遍历
和先序遍历的差别仅在于在遍历完左子树后再输出右节点,再遍历右子树
java实现:
1 | public void stackDFS2(biNode root){ |
后序遍历
后序遍历相对复杂,先序和中序遍历不需要知道右子树是否遍历完成便可以将父节点出栈输出,而后序遍历我们需要保留每一个父节点是否左右子树都遍历完成才能输出。
用三个状态来表示每个节点的遍历情况。我们再维护一个栈statusStack来储存这个状态。在将一个父节点入栈的同时我们将状态0压栈。开始遍历左子树并将父节点的状态从0改为1。当左子树遍历完成,开始遍历右子树并将父节点的状态从1改为2,当右子树遍历完成(右孩子=null)时判断父节点的状态如果为2,则父节点出栈
java实现:
1 | public void stackDFS3(biNode root){ |
广度优先遍历
用队列实现二叉树的广度优先遍历,将根节点放入队列,然后开始遍历队列,将队列头节点出队列,将该节点的左右孩子入队列,直至队列为空。
java实现:
1 | public void BFS(biNode root){ |